/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package utils.conexao;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInput;
import java.io.ObjectInputStream;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import ui.Principal;

/**
 *
 * @author Oliver Kraemer
 */
public class BinaryFile implements IDataBase {

    @Override
    public boolean inserir(Entity e) {
        ArrayList<Entity> rows = loadTable(e);
        rows.add(e);
        return commit(e, rows);
    }

    @Override
    public boolean alterar(Entity e) {
        ArrayList<Entity> rows = loadTable(e);
        
        for (int i = 0; i < rows.size(); i++) {
            if ( rows.get(i).getId() == e.getId() ) {
                rows.set(i, e);
                break;
            }
        }
        
        return commit(e, rows);
    }

    @Override
    public boolean excluir(Entity e) {
        ArrayList<Entity> rows = loadTable(e);
        
        for (int i = 0; i < rows.size(); i++) {
            if ( rows.get(i).getId() == e.getId() ) {
                rows.remove(i);
                break;
            }
        }
        
        return commit(e, rows);
    }

    @Override
    public void generateNextCode(Field f, Entity e) {
        ArrayList<Entity> rows = loadTable(e);

        try {
            if (rows.isEmpty()) {
                f.setInt(e, 1);
            } else {
                f.setInt(e, f.getInt(rows.get(rows.size()-1))+1);
            }
        } catch (IllegalArgumentException ex) {
            Logger.getLogger(BinaryFile.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            Logger.getLogger(BinaryFile.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    private ArrayList<Entity> loadTable(Entity e) {
        if ((new File(getTableName(e)).exists())) {
            try {
                InputStream file = new FileInputStream(getTableName(e));
                InputStream buffer = new BufferedInputStream(file);
                ObjectInput input = new ObjectInputStream(buffer);

                return (ArrayList<Entity>) input.readObject();
            } catch (FileNotFoundException ex) {
                System.out.println(ex.getMessage());
            } catch (IOException ex) {
                System.out.println(ex.getMessage());
            } catch (ClassNotFoundException ex) {
                Logger.getLogger(Principal.class.getName()).log(Level.SEVERE, null, ex);
            }
        }

        return new ArrayList<>();
    }

    private boolean commit(Entity e, ArrayList<Entity> rows) {
        try {
            OutputStream file = new FileOutputStream(getTableName(e));
            OutputStream buffer = new BufferedOutputStream(file);
            ObjectOutput output = new ObjectOutputStream(buffer);

            try {
                output.writeObject(rows);
            } finally {
                output.close();
            }
            
            return true;
        } catch (IOException ex) {
            Logger.getLogger(Principal.class.getName()).log(Level.SEVERE, null, ex);
        }
        
        return false;
    }

    private String getTableName(Entity e) {
        File f = new File("bd/");
        if (!f.exists()) {
            f.mkdir();
        }

        return "bd/" + e.getClass().getSimpleName().toLowerCase() + ".data";
    }
    
    @Override
    public ArrayList getAll(Class c) {
        try {
            return loadTable((Entity) c.newInstance());
        } catch (InstantiationException ex) {
            Logger.getLogger(BinaryFile.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            Logger.getLogger(BinaryFile.class.getName()).log(Level.SEVERE, null, ex);
        }
        
        return new ArrayList();
    }
}
